package bebetes.test;

import java.awt.Color;
import java.util.ArrayList;

import junit.framework.TestCase;
import bebetes.BebeteHasard;
import bebetes.ChampDeBebetes;

/**
 * Classe de tests pour la classe {@link BebeteHasard}.
 * 
 * @author COLLET Philippe
 * @author gnpt
 */
public class BebeteHasardTest1 extends TestCase {
	// La bébête
	private BebeteHasard bebeteHasard = null;
	// Le champ de bébêtes
	private ChampDeBebetes champ = new ChampDeBebetes(640, 480, 0);

	@Override
	protected void setUp() throws Exception {
		super.setUp();
		/* position de la bebete par défaut, au centre, angle a 0, vitesse a 10 */
		this.bebeteHasard = new BebeteHasard(this.champ, 320, 240, 0.0F, 10.0F,
				Color.RED);
		ArrayList<BebeteHasard> l = new ArrayList<BebeteHasard>();
		l.add(this.bebeteHasard);
		this.champ.setBebetes(l);
	}

	@Override
	protected void tearDown() throws Exception {
		this.bebeteHasard = null;
		this.champ = null;
		super.tearDown();
	}

	/**
	 * Test un déplacement de la bébête au milieu du champ.
	 */
	public void testEffectueDeplacementMilieu() {
		// mise en place : rien a changer, juste sauvegarder les anciennes
		// valeurs pour l'oracle
		float oldvit = this.bebeteHasard.getVitesseCourante();
		float olddir = this.bebeteHasard.getDirectionCourante();
		this.bebeteHasard.effectueDeplacement();
		// oracle
		assertEquals("direction inchangée", this.bebeteHasard
				.getDirectionCourante(), olddir, 0.1f);
		assertEquals("vitesse inchangée", this.bebeteHasard
				.getVitesseCourante(), oldvit, 0.1f);
	}

	/**
	 * Test si la bébête rebondit bien sur le bord droit du champ.
	 */
	public void testEffectueDeplacementDepassementDroit() {
		// mise en place
		this.bebeteHasard.setX(637);
		this.bebeteHasard.setY(240);
		this.bebeteHasard.setDirectionCourante((float) Math.PI / 5);
		// test
		this.bebeteHasard.effectueDeplacement();
		// oracle
		assertEquals("nouvelle direction après rebond", this.bebeteHasard
				.getDirectionCourante(), (float) (Math.PI * 4 / 5), 0.1f);
		assertTrue("x revenu dans le champ", this.bebeteHasard.getX() < 640);
		assertTrue("y plus grand", this.bebeteHasard.getY() > 240);
	}

	/**
	 * Test si la bébête rebondit bien sur le bord gauche du champ.
	 */
	public void testEffectueDeplacementDepassementGauche() {
		// mise en place
		this.bebeteHasard.setX(3);
		this.bebeteHasard.setY(240);
		this.bebeteHasard.setDirectionCourante((float) Math.PI * 6 / 5);
		// test
		this.bebeteHasard.effectueDeplacement();
		// oracle
		assertEquals("nouvelle direction après rebond", this.bebeteHasard
				.getDirectionCourante(), (float) (Math.PI * 9 / 5), 0.1f);
		assertTrue("x revenu dans le champ", this.bebeteHasard.getX() > 0);
		assertTrue("y plus petit", this.bebeteHasard.getY() < 240);
	}

	/**
	 * Test si la bébête rebondit bien sur le bord haut du champ.
	 */
	public void testEffectueDeplacementDepassementHaut() {
		// mise en place
		this.bebeteHasard.setX(320);
		this.bebeteHasard.setY(4);
		this.bebeteHasard.setDirectionCourante((float) Math.PI * 6 / 5);
		// test
		this.bebeteHasard.effectueDeplacement();
		// oracle
		assertEquals("nouvelle direction après rebond", this.bebeteHasard
				.getDirectionCourante(), (float) (Math.PI * 4 / 5), 0.1f);
		assertTrue("x plus petit", this.bebeteHasard.getX() < 320);
		assertTrue("y revenu dans le champ", this.bebeteHasard.getY() > 0);
	}

	/**
	 * Test si la bébête rebondit bien sur le bord bas du champ.
	 */
	public void testEffectueDeplacementDepassementBas() {
		// mise en place
		this.bebeteHasard.setX(320);
		this.bebeteHasard.setY(477);
		this.bebeteHasard.setDirectionCourante((float) Math.PI / 5);
		// test
		this.bebeteHasard.effectueDeplacement();
		// oracle
		assertEquals("nouvelle direction après rebond", this.bebeteHasard
				.getDirectionCourante(), (float) (Math.PI * 9 / 5), 0.1f);
		assertTrue("x plus grand", this.bebeteHasard.getX() > 320);
		assertTrue("y revenu dans le champ", this.bebeteHasard.getY() < 480);
	}

	/**
	 * Test de rebond de la bébête dans le coin haut gauche du champ.
	 */
	public void testEffectueDeplacementZeroZeroAngle45() {
		// mise en place
		this.bebeteHasard.setX(3);
		this.bebeteHasard.setY(3);
		this.bebeteHasard.setDirectionCourante((float) Math.PI * 5 / 4);
		// test
		this.bebeteHasard.effectueDeplacement();
		// oracle
		assertEquals("nouvelle direction après rebond", (float) (Math.PI / 4),
				this.bebeteHasard.getDirectionCourante(), 0.1f);
		// le comportement d'un rebond dans l'angle n'est pas défini. Cela
		// dépendrait effectivement de la forme qu'a l'objet, etc...
		assertTrue("x revenu dans le champ, x = " + this.bebeteHasard.getX(),
				0 < this.bebeteHasard.getX() && this.bebeteHasard.getX() < 12);
		assertTrue("y revenu dans le champ, y = " + this.bebeteHasard.getY(),
				0 < this.bebeteHasard.getY() && this.bebeteHasard.getY() < 12);
	}

	/**
	 * Test de rebond de la bébête dans le coin haut gauche du champ.
	 */
	public void testEffectueDeplacementZeroZeroTravers() {
		// mise en place
		this.bebeteHasard.setX(1);
		this.bebeteHasard.setY(1);
		this.bebeteHasard.setDirectionCourante((float) Math.PI * 9 / 8);
		// test
		this.bebeteHasard.effectueDeplacement();
		// oracle
		assertEquals("nouvelle direction après rebond", (float) (Math.PI / 8),
				this.bebeteHasard.getDirectionCourante(), 0.1f);
		// le comportement d'un rebond dans l'angle n'est pas défini. Cela
		// dépendrait effectivement de la forme qu'a l'objet, etc...
		assertTrue("x revenu dans le champ, x = " + this.bebeteHasard.getX(),
				0 < this.bebeteHasard.getX() && this.bebeteHasard.getX() < 12);
		assertTrue("y revenu dans le champ, y = " + this.bebeteHasard.getY(),
				0 < this.bebeteHasard.getY() && this.bebeteHasard.getY() < 12);
	}
}
